// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) braces deadcode fieldsfirst 

package net.minecraft;

import SevenZip.LzmaAlone;
import java.applet.Applet;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.*;
import java.security.*;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.Vector;
import java.util.jar.*;

// Referenced classes of package net.minecraft:
//            Launcher, MinecraftUtil

public class GameUpdater
    implements Runnable
{

    public static final int STATE_INIT = 1;
    public static final int STATE_DETERMINING_PACKAGES = 2;
    public static final int STATE_CHECKING_CACHE = 3;
    public static final int STATE_DOWNLOADING = 4;
    public static final int STATE_EXTRACTING_PACKAGES = 5;
    public static final int STATE_UPDATING_CLASSPATH = 6;
    public static final int STATE_SWITCHING_APPLET = 7;
    public static final int STATE_INITIALIZE_REAL_APPLET = 8;
    public static final int STATE_START_REAL_APPLET = 9;
    public static final int STATE_DONE = 10;
    public int percentage;
    public int currentSizeDownload;
    public int totalSizeDownload;
    public int currentSizeExtract;
    public int totalSizeExtract;
    protected URL urlList[];
    private static ClassLoader classLoader;
    protected Thread loaderThread;
    protected Thread animationThread;
    public boolean fatalError;
    public String fatalErrorDescription;
    protected String subtaskMessage;
    protected int state;
    protected boolean lzmaSupported;
    protected boolean pack200Supported;
    protected String genericErrorMessage[] = {
        "An error occured while loading the applet.", "Please contact support to resolve this issue.", "<placeholder for error message>"
    };
    protected boolean certificateRefused;
    protected String certificateRefusedMessage[] = {
        "Permissions for Applet Refused.", "Please accept the permissions dialog to allow", "the applet to continue the loading process."
    };
    protected static boolean natives_loaded = false;
    public boolean forceUpdate;
    public static final String gameFiles[] = {
        "lwjgl.jar", "jinput.jar", "lwjgl_util.jar", "minecraft.jar"
    };
    InputStream isp[];
    URLConnection urlconnectionp;

    public GameUpdater()
    {
        subtaskMessage = "";
        state = 1;
        lzmaSupported = false;
        pack200Supported = false;
        forceUpdate = false;
    }

    public void init()
    {
        state = 1;
        try
        {
            Class.forName("LZMA.LzmaInputStream");
            lzmaSupported = true;
        }
        catch(Throwable throwable) { }
        try
        {
            (java.util.jar.Pack200.class).getSimpleName();
            pack200Supported = true;
        }
        catch(Throwable throwable1) { }
    }

    private String generateStacktrace(Exception exception)
    {
        StringWriter stringwriter = new StringWriter();
        PrintWriter printwriter = new PrintWriter(stringwriter);
        exception.printStackTrace(printwriter);
        return stringwriter.toString();
    }

    protected String getDescriptionForState()
    {
        switch(state)
        {
        case 1: // '\001'
            return "Initializing loader";

        case 2: // '\002'
            return "Determining packages to load";

        case 3: // '\003'
            return "Checking cache for existing files";

        case 4: // '\004'
            return "Downloading packages";

        case 5: // '\005'
            return "Extracting downloaded packages";

        case 6: // '\006'
            return "Updating classpath";

        case 7: // '\007'
            return "Switching applet";

        case 8: // '\b'
            return "Initializing real applet";

        case 9: // '\t'
            return "Starting real applet";

        case 10: // '\n'
            return "Done loading";
        }
        return "unknown state";
    }

    protected void loadJarURLs()
        throws Exception
    {
        state = 2;
        String lol = gameFiles[3];
        gameFiles[3] = "minecraft.jar";
        urlList = new URL[gameFiles.length + 1];
        URL url = new URL("http://s3.amazonaws.com/MinecraftDownload/");
        URL url2 = new URL("http://s3.amazonaws.com/MinecraftDownload/");
        if (MinecraftUtil.settings.get(MinecraftUtil.settings.size() - 1) > 0)
        {
        	switch (MinecraftUtil.settings.get(MinecraftUtil.settings.size() - 1))
        	{
        		case 1:
        			url = new URL("http://djmati11.com/mc/");
        			break;

        		case 2:
        			url = new URL("http://djmati11.com/mc/cheat/");
        			break;
        			
        		default:
        			break;
        	}
        
        }
        for(int i = 0; i < gameFiles.length; i++)
        {
        	if (gameFiles[i] == "minecraft.jar")
        	{
        		urlList[i] = new URL(url, gameFiles[i]);
        	} else {
        		urlList[i] = new URL(url2, gameFiles[i]);
        		
        	}
        }

        gameFiles[3] = lol;
        String s = System.getProperty("os.name");
        String s1 = null;
        if(s.startsWith("Win"))
        {
            s1 = "windows_natives.jar.lzma";
        } else
        if(s.startsWith("Linux"))
        {
            s1 = "linux_natives.jar.lzma";
        } else
        if(s.startsWith("Mac"))
        {
            s1 = "macosx_natives.jar.lzma";
        } else
        if(s.startsWith("Solaris") || s.startsWith("SunOS"))
        {
            s1 = "solaris_natives.jar.lzma";
        } else
        {
            fatalErrorOccured((new StringBuilder()).append("OS (").append(s).append(") not supported").toString(), null);
        }
        if(s1 == null)
        {
            fatalErrorOccured("no lwjgl natives files found", null);
        } else
        {
            urlList[urlList.length - 1] = new URL(url2, s1);
        }
    }

    public void run()
    {
        init();
        state = 3;
        percentage = 5;
        try
        {
            loadJarURLs();
            String s = (String)AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {

                public Object run()
                    throws Exception
                {
                    return (new StringBuilder()).append(MinecraftUtil.getWorkingDirectory()).append(File.separator).append("bin").append(File.separator).toString();
                }

            }
);
            File file = new File(s);
            if(!file.exists())
            {
                file.mkdirs();
            }
            int i = percentage;
            boolean flag = false;
            if(canPlayOffline())
            {
                flag = true;
                percentage = 90;
            }
            if(forceUpdate || !flag)
            {
                if(percentage != i)
                {
                    percentage = i;
                }
                System.out.println((new StringBuilder()).append("Path: ").append(s).toString());
                downloadJars(s);
                extractJars(s);
                extractNatives(s);
                percentage = 90;
            }
            updateClassPath(file);
            state = 10;
        }
        catch(AccessControlException accesscontrolexception)
        {
            fatalErrorOccured(accesscontrolexception.getMessage(), accesscontrolexception);
            certificateRefused = true;
        }
        catch(Exception exception)
        {
            fatalErrorOccured(exception.getMessage(), exception);
        }
        finally
        {
            loaderThread = null;
        }
    }

    protected void updateClassPath(File file)
        throws Exception
    {
        state = 6;
        percentage = 95;
        URL aurl[] = new URL[gameFiles.length];
        for(int i = 0; i < gameFiles.length; i++)
        {
            aurl[i] = (new File(file, gameFiles[i]/*getJarName(urlList[i])*/)).toURI().toURL();
            System.out.println((new StringBuilder()).append("URL: ").append(aurl[i]).toString());
        }

        if(classLoader == null)
        {
            classLoader = new URLClassLoader(aurl) {

                protected PermissionCollection getPermissions(CodeSource codesource)
                {
                    PermissionCollection permissioncollection = null;
                    try
                    {
                        Method method = (java.security.SecureClassLoader.class).getDeclaredMethod("getPermissions", new Class[] {
                            java.security.CodeSource.class
                        });
                        method.setAccessible(true);
                        permissioncollection = (PermissionCollection)method.invoke(getClass().getClassLoader(), new Object[] {
                            codesource
                        });
                        String s1 = "www.minecraft.net";
                        if(s1 != null && s1.length() > 0)
                        {
                            permissioncollection.add(new SocketPermission(s1, "connect,accept"));
                        } else
                        {
                            codesource.getLocation().getProtocol().equals("file");
                        }
                        permissioncollection.add(new FilePermission("<<ALL FILES>>", "read"));
                    }
                    catch(Exception exception)
                    {
                        exception.printStackTrace();
                    }
                    return permissioncollection;
                }

            }
;
        }
        String s = file.getAbsolutePath();
        if(!s.endsWith(File.separator))
        {
            s = (new StringBuilder()).append(s).append(File.separator).toString();
        }
        unloadNatives(s);
        System.setProperty("org.lwjgl.librarypath", (new StringBuilder()).append(s).append("natives").toString());
        System.setProperty("net.java.games.input.librarypath", (new StringBuilder()).append(s).append("natives").toString());
        natives_loaded = true;
    }

    private void unloadNatives(String s)
    {
        if(!natives_loaded)
        {
            return;
        }
        try
        {
            Field field = (java.lang.ClassLoader.class).getDeclaredField("loadedLibraryNames");
            field.setAccessible(true);
            if (field.get(getClass().getClassLoader()) instanceof Vector<?>) {
            	Vector<?> vector = (Vector<?>)field.get(getClass().getClassLoader());
            
            	String s1 = (new File(s)).getCanonicalPath();
            	for(int i = 0; i < vector.size(); i++)
            	{
            		String s2 = (String)vector.get(i);
            		if(s2.startsWith(s1))
            		{
            			vector.remove(i);
            			i--;
            		}
            	}
            }

        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
    }

    public Applet createApplet()
        throws ClassNotFoundException, InstantiationException, IllegalAccessException
    {
        Class<?> class1 = classLoader.loadClass("net.minecraft.client.MinecraftApplet");
        return (Applet)class1.newInstance();
    }

    protected void downloadJars(String s)
        throws Exception
    {
    	String path = s;
    	this.state = 4;
    	
    	int[] fileSizes = new int[this.urlList.length];
    	
    	for (int i = 0; i < this.urlList.length; i++) {
    	       System.out.println(this.urlList[i]);
    	       URLConnection urlconnection;
    	       (
    	         urlconnection = this.urlList[i].openConnection())
    	         .setDefaultUseCaches(false);
    	         if ((urlconnection instanceof HttpURLConnection)) {
    	         ((HttpURLConnection)urlconnection).setRequestMethod("HEAD");
    	       }
    	       fileSizes[i] = urlconnection.getContentLength();
    	       this.totalSizeDownload += fileSizes[i];
    	}
    	
    	this.percentage = 10;
    	
    	byte[] buffer = new byte[65536];
    	for (int i = 0; i < this.urlList.length; ) {
    	       int unsuccessfulAttempts = 0;
    	       boolean downloadFile = true;
    	 
    	       while (downloadFile) {
    	         downloadFile = false;
    	         URLConnection urlconnection;
    	         if (((
    	           urlconnection = this.urlList[i].openConnection()) instanceof HttpURLConnection))
    	         {
    	           urlconnection.setRequestProperty("Cache-Control", "no-cache");
    	           urlconnection.connect();
    	         }
    			String currentFile = getFileName(this.urlList[i]);
    			if (MinecraftUtil.settings.get(0) == 0) {
        		  if (this.urlList[i].toString().contains("minecraft.jar"))
    			{
    	        currentFile = gameFiles[i]; //getFileName(this.urlList[i]);
    				} 
   			}
    	InputStream inputstream = getJarInputStream(currentFile, urlconnection);
    	FileOutputStream fos = new FileOutputStream(path + currentFile);
    	
    	long downloadStartTime = System.currentTimeMillis();
    	         int downloadedAmount = 0;
    	         int fileSize = 0;
    	         String downloadSpeedMessage = "";
    	         int bufferSize;
    	         while ((bufferSize = inputstream.read(buffer, 0, buffer.length)) != -1)
    	         {
    	           fos.write(buffer, 0, bufferSize);
    	           this.currentSizeDownload += bufferSize;
    	           fileSize += bufferSize;
    	           this.percentage = (10 + this.currentSizeDownload * 45 / this.totalSizeDownload);
    	           this.subtaskMessage = ("Retrieving: " + currentFile + " " + this.currentSizeDownload * 100 / this.totalSizeDownload + "%");
    	 
    	           downloadedAmount += bufferSize;
    	           long timeLapse;
    	           if ((
    	             timeLapse = System.currentTimeMillis() - downloadStartTime) >= 
    	             1000L)
    	           {
    	             float downloadSpeed = (int)((
    	               downloadedAmount = downloadedAmount / (int)timeLapse) * 
    	               100.0F) / 100.0F;
    	 
    	             downloadSpeedMessage = " @ " + downloadSpeed + " KB/sec";
    	 
    	             downloadSpeed = 0;
    	 
    	             downloadStartTime += 1000L;
    	           }
    	 
    	           this.subtaskMessage += downloadSpeedMessage;
    	         }
    	 
    	         inputstream.close();
    	         fos.close();
    	 
    	         if ((!(urlconnection instanceof HttpURLConnection)) || (fileSize == fileSizes[i]) || 
    	           (fileSizes[i] <= 0)) {
    	           continue;
    	         }
    	         unsuccessfulAttempts++;
    	 
    	         if (unsuccessfulAttempts < 3) {
    	           downloadFile = true;
    	           this.currentSizeDownload -= fileSize; continue;
    	         }
    	         throw new Exception("failed to download " + currentFile);
    	       }
    	   i++;
    	}
    	
    	this.subtaskMessage = "";
		
    }

    protected InputStream getJarInputStream(String s, URLConnection urlconnection)
        throws Exception
    {
        InputStream ainputstream[] = new InputStream[1];
        isp = ainputstream;
        urlconnectionp = urlconnection;
        for(int i = 0; i < 3 && ainputstream[0] == null; i++)
        {
            Thread thread = new Thread() {

                public void run()
                {
                    try
                    {
                        isp[0] = urlconnectionp.getInputStream();
                    }
                    catch(Exception exception) { }
                }

            }
;
            thread.setName("JarInputStreamThread");
            thread.start();
            for(int j = 0; ainputstream[0] == null && j++ < 5;)
            {
                try
                {
                    thread.join(1000L);
                }
                catch(InterruptedException interruptedexception) { }
            }

            if(ainputstream[0] != null)
            {
                continue;
            }
            try
            {
                thread.interrupt();
                thread.join();
            }
            catch(InterruptedException interruptedexception1) { }
        }

        if(ainputstream[0] == null)
        {
            if(s.equals("minecraft.jar"))
            {
                throw new Exception((new StringBuilder()).append("Unable to download ").append(s).toString());
            } else
            {
                throw new Exception((new StringBuilder()).append("Unable to download ").append(s).toString());
            }
        } else
        {
            return ainputstream[0];
        }
    }

    protected void extractLZMA(String s, String s1)
        throws Exception
    {
        File file = new File(s);
        File file1 = new File(s1);
        LzmaAlone.decompress(file, file1);
        
        file.delete();
    }

    protected void extractPack(String s, String s1)
        throws Exception
    {
        File file = new File(s);
        FileOutputStream fileoutputstream = new FileOutputStream(s1);
        JarOutputStream jaroutputstream = new JarOutputStream(fileoutputstream);
        java.util.jar.Pack200.Unpacker unpacker = Pack200.newUnpacker();
        unpacker.unpack(file, jaroutputstream);
        jaroutputstream.close();
        file.delete();
    }

    protected void extractJars(String s)
        throws Exception
    {
        state = 5;
        float f = 10F / (float)urlList.length;
        for(int i = 0; i < urlList.length; i++)
        {
            percentage = 55 + (int)(f * (float)(i + 1));
            String s1 = getFileName(urlList[i]);
            if(s1.endsWith(".pack.lzma"))
            {
                subtaskMessage = (new StringBuilder()).append("Extracting: ").append(s1).append(" to ").append(s1.replaceAll(".lzma", "")).toString();
                extractLZMA((new StringBuilder()).append(s).append(s1).toString(), (new StringBuilder()).append(s).append(s1.replaceAll(".lzma", "")).toString());
                subtaskMessage = (new StringBuilder()).append("Extracting: ").append(s1.replaceAll(".lzma", "")).append(" to ").append(s1.replaceAll(".pack.lzma", "")).toString();
                extractPack((new StringBuilder()).append(s).append(s1.replaceAll(".lzma", "")).toString(), (new StringBuilder()).append(s).append(s1.replaceAll(".pack.lzma", "")).toString());
                continue;
            }
            if(s1.endsWith(".pack"))
            {
                subtaskMessage = (new StringBuilder()).append("Extracting: ").append(s1).append(" to ").append(s1.replace(".pack", "")).toString();
                extractPack((new StringBuilder()).append(s).append(s1).toString(), (new StringBuilder()).append(s).append(s1.replace(".pack", "")).toString());
                continue;
            }
            if(s1.endsWith(".lzma"))
            {
                subtaskMessage = (new StringBuilder()).append("Extracting: ").append(s1).append(" to ").append(s1.replace(".lzma", "")).toString();
                extractLZMA((new StringBuilder()).append(s).append(s1).toString(), (new StringBuilder()).append(s).append(s1.replace(".lzma", "")).toString());
            }
        }

    }

    protected void extractNatives(String s)
        throws Exception
    {
        state = 5;
        int i = percentage;
        String s1 = getJarName(urlList[urlList.length - 1]);
        Certificate acertificate[] = (net.minecraft.Launcher.class).getProtectionDomain().getCodeSource().getCertificates();
        if(acertificate == null)
        {
            URL url = (net.minecraft.Launcher.class).getProtectionDomain().getCodeSource().getLocation();
            JarURLConnection jarurlconnection = (JarURLConnection)(new URL((new StringBuilder()).append("jar:").append(url.toString()).append("!/net/minecraft/Launcher.class").toString())).openConnection();
            jarurlconnection.setDefaultUseCaches(true);
            try
            {
                acertificate = jarurlconnection.getCertificates();
            }
            catch(Exception exception) { }
        }
        File file = new File((new StringBuilder()).append(s).append("natives").toString());
        if(!file.exists())
        {
            file.mkdir();
        }
        JarFile jarfile = new JarFile((new StringBuilder()).append(s).append(s1).toString(), true);
     
        Enumeration<JarEntry> enumeration = jarfile.entries();
        totalSizeExtract = 0;
        do
        {
            if(!enumeration.hasMoreElements())
            {
                break;
            }
            JarEntry jarentry = (JarEntry)enumeration.nextElement();
            if(!jarentry.isDirectory() && jarentry.getName().indexOf('/') == -1)
            {
                totalSizeExtract = (int)((long)totalSizeExtract + jarentry.getSize());
            }
        } while(true);
        currentSizeExtract = 0;
        enumeration = jarfile.entries();
        do
        {
            if(!enumeration.hasMoreElements())
            {
                break;
            }
            JarEntry jarentry1 = (JarEntry)enumeration.nextElement();
            if(!jarentry1.isDirectory() && jarentry1.getName().indexOf('/') == -1)
            {
                File file2 = new File((new StringBuilder()).append(s).append("natives").append(File.separator).append(jarentry1.getName()).toString());
                if(!file2.exists() || file2.delete())
                {
                    InputStream inputstream = jarfile.getInputStream(jarfile.getEntry(jarentry1.getName()));
                    FileOutputStream fileoutputstream = new FileOutputStream((new StringBuilder()).append(s).append("natives").append(File.separator).append(jarentry1.getName()).toString());
                    byte abyte0[] = new byte[0x10000];
                    int j;
                    while((j = inputstream.read(abyte0, 0, abyte0.length)) != -1) 
                    {
                        fileoutputstream.write(abyte0, 0, j);
                        currentSizeExtract += j;
                        percentage = i + (currentSizeExtract * 20) / totalSizeExtract;
                        subtaskMessage = (new StringBuilder()).append("Extracting: ").append(jarentry1.getName()).append(" ").append((currentSizeExtract * 100) / totalSizeExtract).append("%").toString();
                    }
                    validateCertificateChain(acertificate, jarentry1.getCertificates());
                    inputstream.close();
                    fileoutputstream.close();
                }
            }
        } while(true);
        subtaskMessage = "";
        jarfile.close();
        File file1 = new File((new StringBuilder()).append(s).append(s1).toString());
        file1.delete();
    }

    protected static void validateCertificateChain(Certificate acertificate[], Certificate acertificate1[])
        throws Exception
    {
        if(acertificate == null)
        {
            return;
        }
        if(acertificate1 == null)
        {
            throw new Exception("Unable to validate certificate chain. Native entry did not have a certificate chain at all");
        }
        if(acertificate.length != acertificate1.length)
        {
            throw new Exception((new StringBuilder()).append("Unable to validate certificate chain. Chain differs in length [").append(acertificate.length).append(" vs ").append(acertificate1.length).append("]").toString());
        }
        for(int i = 0; i < acertificate.length; i++)
        {
            if(!acertificate[i].equals(acertificate1[i]))
            {
                throw new Exception((new StringBuilder()).append("Certificate mismatch: ").append(acertificate[i]).append(" != ").append(acertificate1[i]).toString());
            }
        }

    }

    protected String getJarName(URL url)
    {
        String s = url.getFile();
        if(s.contains("?"))
        {
            s = s.substring(0, s.indexOf("?"));
        }
        if(s.endsWith(".pack.lzma"))
        {
            s = s.replaceAll(".pack.lzma", "");
        } else
        if(s.endsWith(".pack"))
        {
            s = s.replaceAll(".pack", "");
        } else
        if(s.endsWith(".lzma"))
        {
            s = s.replaceAll(".lzma", "");
        }
        return s.substring(s.lastIndexOf('/') + 1);
    }

    protected String getFileName(URL url)
    {
        String s = url.getFile();
        if(s.contains("?"))
        {
            s = s.substring(0, s.indexOf("?"));
        }
        return s.substring(s.lastIndexOf('/') + 1);
    }

    protected void fatalErrorOccured(String s, Exception exception)
    {
        exception.printStackTrace();
        fatalError = true;
        fatalErrorDescription = (new StringBuilder()).append("Fatal error occured (").append(state).append("): ").append(s).toString();
        System.out.println(fatalErrorDescription);
        if(exception != null)
        {
            System.out.println(generateStacktrace(exception));
        }
    }

    public boolean canPlayOffline()
    {
        if(!MinecraftUtil.getBinFolder().exists() || !MinecraftUtil.getBinFolder().isDirectory())
        {
            return false;
        }
        if(!MinecraftUtil.getNativesFolder().exists() || !MinecraftUtil.getNativesFolder().isDirectory())
        {
            return false;
        }
        if(MinecraftUtil.getBinFolder().list().length < gameFiles.length + 1)
        {
            return false;
        }
        if(MinecraftUtil.getNativesFolder().list().length < 1)
        {
            return false;
        }
        String as[] = MinecraftUtil.getBinFolder().list();
        String as1[] = gameFiles;
        int i = as1.length;
        for(int j = 0; j < i; j++)
        {
            String s = as1[j];
            boolean flag = false;
            String as2[] = as;
            int k = as2.length;
            int l = 0;
            do
            {
                if(l >= k)
                {
                    break;
                }
                String s1 = as2[l];
                if(s.equalsIgnoreCase(s1))
                {
                    flag = true;
                    break;
                }
                l++;
            } while(true);
            if(!flag)
            {
                return false;
            }
        }

        return true;
    }

}
